<template>
  <g class="node" ref="node" :data-id="id" @click="click">
    <g>
      <rect rx="5" ry="5" width="120" height="30" :fill="bgcolor" :stroke="strokeColor" :stroke-width="strokeWidth"/>
      <text x="50" y="20" fill="black">{{ text }}</text>
    </g>
    <node-point v-if="hasHead" :category="1" ref="head" @update="updateHead"></node-point>
    <node-point v-if="hasTail" :category="2" ref="tail" @update="updateTail"></node-point>
  </g>
</template>

<script>
import { TweenMax } from 'gsap'
import Draggable from 'gsap/Draggable'
import NodePoint from '@/components/NodePoint'

export default {
  components: {
    NodePoint
  },
  props: {
    id: {
      default: -1
    },
    x: {
      default: 0
    },
    y: {
      default: 0
    },
    bgcolor: {
      default: '#409eff'
    },
    borderColor: {
      default: '#5F4C0B'
    },
    selectedColor: {
      default: '#F5DA81'
    },
    moveType: {
      default: 'x,y'
    },
    bounds: {
      default: '.container'
    },
    edgeResistance: {
      default: 0.65
    },
    cursor: {
      default: 'default'
    },
    text: {
      default: '新节点'
    },
    hasHead: { // 是否允许有输入节点
      default: true
    },
    hasTail: { // 是否允许有输出节点
      default: true
    }
  },
  data () {
    return {
      type: 'node',
      r: 5,
      isMouseOverHead: false,
      isMouseOverTail: false,
      head: { x: 0, y: 0 },
      tail: { x: 0, y: 0 },
      prev: null,
      next: null,
      isSelected: false // 是否被选中
    }
  },
  methods: {
    setPrev (vm) {
      this.prev = vm
    },
    setNext (vm) {
      this.next = vm
    },
    enableDrag () {
      this.node.enable()
    },
    disableDrag () {
      this.node.disable()
    },
    updateHead (point) {
      this.head.x = point.x
      this.head.y = point.y
    },
    updateTail (point) {
      this.tail.x = point.x
      this.tail.y = point.y
    },
    setSelected (isSelected = true) {
      this.isSelected = isSelected
      if (isSelected) {
        this.$parent.addSelectedLinesByNodeId(this.id)
      }
    },
    click (event) {
      event.stopPropagation()
    },
    remove () {
      this.$parent.removeNode(this.id)
    },
    getHead () {
      return this.head
    },
    getTail () {
      return this.tail
    },
    /**
     * 更新头节点与尾节点位置，如果有的话
     * @Author   Jiangzhiwei
     * @datetime 2021-10-22T10:56:39+0800
     */
    refreshPoint () {
      if (this.hasHead) {
        this.$refs.head.refreshPoint()
      }
      if (this.hasTail) {
        this.$refs.tail.refreshPoint()
      }
    },
    /**
     * 更新节点位置
     * @param    {Number} x 相对svg的x
     * @param    {Number} y 相对svg的y
     * @Author   Jiangzhiwei
     * @datetime 2021-10-22T11:30:06+0800
     */
    refreshPosition (x, y) {
      TweenMax.to(this.$refs.node, 0, { x, y })
      this.refreshPoint()
    },
    init () {
      const container = this.$parent
      this.box = container.$el
      this.node = Draggable.create(this.$refs.node, {
        type: this.moveType,
        edgeResistance: this.edgeResistance,
        cursor: this.cursor,
        activeCursor: this.cursor,
        bounds: this.box,
        inertia: true,
        onPress: event => {
          // console.log('onPress')
          if (this.$parent.hasSelected(this)) { // 如果已经被选中，则标记
            this.pressed = true // 标记选中时按下
            this.pressShift = event.shiftKey // 标记按下shift
            // this.$parent.selectComps(this)
          } else { // 未被选中
            this.$parent.singleSelect(this, event.shiftKey)
          }
          event.stopPropagation()
        },
        onDrag: event => {
          this.refreshPoint()
        },
        onDragEnd: event => {
          this.refreshPoint()
          const matrix = this.$refs.node.transform.baseVal[0].matrix
          this.$parent.addHistory({
            type: 'moveNode',
            data: { id: this.id, x: matrix.e, y: matrix.f }
          })
          // console.log(matrix.e, matrix.f)
          // console.log('onDragEnd')
        },
        onClick: event => {
          // console.log('onClick')
          // 进入onClick，表明未拖动
          // this.$parent.singleSelect(this, event.shiftKey)
          if (this.pressed) { // 选中时按下
            if (this.pressShift) { // 按下了shift键
              this.$parent.cancelSelectComps(this) // 取消选中
            } else { // 未按下shift键
              this.$parent.singleSelect(this) // 单选
            }
          }
          this.pressed = false // 标记未按下
        }
        // onRelease: event => {
        //   console.log('onRelease')
        // },
        // onMove: event => {
        //   console.log('onMove')
        // },
        // onLockAxis: event => {
        //   console.log('onLockAxis')
        // }
      })[0]
      this.refreshPosition(this.x, this.y)
    }
  },
  computed: {
    strokeColor () {
      return this.isSelected ? this.selectedColor : this.borderColor
    },
    strokeWidth () {
      return this.isSelected ? 2 : 1
    }
  },
  mounted () {
    this.init()
  }
}
</script>

<style scoped lang="scss">
  .node {
    // cursor: default !important;
  }
</style>
